(function($) {

    var session = chrome.extension.getBackgroundPage().session;
    var giftTokens = [];
    var acceptTab = null;
    var acceptedItems = {};
    var invalidItems = {};

    function cleanUpPastedText(tokens) {
        var joinPattern = /\s/g;
        var cleanupPattern = /[^A-Za-z0-9\+\/=\-&<>]/g;
        tokens = tokens.replace(joinPattern, "");
        tokens = tokens.replace(cleanupPattern, "");
        return tokens;
    }

    function getAcceptItemParams(token) {

        var itemId = token["itemId"];
        var senderId = token["senderId"];
        var giftToken = token["giftToken"];

        var params = {
            "giftItemId": itemId,
            "senderId": senderId,
            "pf_giftToken": giftToken,
            "pf_cols": "1",
            "pf_content_body": "Here is one Gift ingredient for you to improve your restaurant's menu! Could you help me by sending one back?",
            "pf_tabName": "RC Friends",
            "pf_content_acceptButton": "Accept Gift",
            "pf_senderId": senderId,
            "pf_requestType": "gift_request",
            "pf_condensed": "true",
            "pf_title": "Friends playing Restaurant City",
            "pf_selectedRows": "1",
            "pf_unselectedRows": "15",
            "pf_iref": "gb",
            "pf_bgImage": "",
            "pf_requestName": "Restaurant City Gift",
            "pf_giftItemId": itemId
        };

        return $.param(params);
    }

    function shouldAcceptGifts() {
        return $("#acceptGifts").is(":checked");
    }

    function acceptItem(token) {
        if (shouldAcceptGifts()) {
            var url = "http://apps.facebook.com/restaurantcity/sticker_click_handler?" + getAcceptItemParams(token);
            if (acceptTab) {
                // reuse existing tab
                chrome.tabs.update(acceptTab.id, {
                    "url": url
                });
            } else {
                // create new tab on first accept request
                chrome.tabs.create({
                    "url": url
                }, function(tab) {
                    acceptTab = tab;
                });
            }
        } else {
            nextItem();
        }
    }

    function extractTokenData(result, giftTokens) {
        var tokenSplitPattern = /([A-Za-z0-9_\.\-]+?)<nofil2000>([A-Za-z0-9_\.\-]+?)<nofil2000>([A-Za-z0-9]+?)<nofil2000>(\d+)/;
        var itemId = result[2];
        var token = result[1];
        try {
            var decoded = window.atob(token);
            var segments = tokenSplitPattern.exec(decoded);
            if (segments) {
                var giftItem = {
                    "itemId": itemId,
                    "giftToken": segments[1],
                    "sessionKey": segments[2],
                    "apiKey": segments[3],
                    "senderId": segments[4]
                };
                giftTokens.push(giftItem);
            }
        } catch (err) {
            // ignore window.atob errors :p
        }
    }

    function getSendItemParams(token) {
        var params = {
            "cmfs_typeahead_req_form_4e45b2392942e9e29807487": "Start typing a name",
            "ids[]": session["fb_sig_user"],
            "pf_session_key": token["sessionKey"],
            "pf_api_key": token["apiKey"],
            "pf_giftToken": token["giftToken"],
            "pf_excludeListForLogging":""
        };
        return $.param(params);
    }

    function sendItem() {
        if (giftTokens.length > 0) {
            var token = giftTokens.pop();
            $("#message").text(giftTokens.length + " tokens remaining");
            if (!isInvalidItem(token.itemId)) {
                var sendUrl = "http://cooking.game.playfish.com/g/fb/cooking/end_send_sticker?" + getSendItemParams(token);
                $.ajax(sendUrl, {
                    success: function() {
                        acceptItem(token);
                    },
                    error: function() {
                        sendItemFailed(token.itemId);
                    }
                });
            } else {
                nextItem();
            }
        }
    }

    function extractTokens() {

        var tokenPattern = /<token>([A-Za-z0-9\+\/=]+?)<\/token>-itemid=(\d+?)&&&&/g;

        var extractedTokens = [];

        var pasteData = cleanUpPastedText($("#tokens").val());

        // extract tokens from pasted data
        do {
            var result = tokenPattern.exec(pasteData);
            if (result) {
                var encodedToken = result[0];
                if (!extractedTokens[encodedToken]) {
                    extractedTokens.push(encodedToken);
                    extractTokenData(result, giftTokens);
                }
            }
        } while (result);

        $("#tokens").val(extractedTokens.join("\n"));

        return giftTokens;
    }

    function generateGiftToken() {

        var tokenData = [
            session["pf_giftToken"],
            session["pf_session_key"],
            session["pf_api_key"],
            session["pf_senderId"]
        ];

        var encodedToken = window.btoa(tokenData.join("<nofil2000>"));

        return "<token>" + encodedToken + "</token>-itemid=" + session["pf_giftItemId"] + "&&&&";
    }

    $(document).ready(function() {

        $("#yourToken").val(generateGiftToken());

        $("#claimGifts").click(function(ev) {
            ev.preventDefault();
            giftTokens = [];
            extractTokens();
            $("#claimGifts,#acceptGifts").attr("disabled", true);
            sendItem();
            return false;
        });
    });

    function getItemKey(itemId) {
        return "itemId_" + itemId;
    }

    function sendItemFailed(itemId) {
        var key = getItemKey(itemId);
        if (key in invalidItems) {
            invalidItems[key]++;
        } else {
            invalidItems[key] = 1;
        }
        nextItem();
    }

    function isInvalidItem(itemId) {
        var key = getItemKey(itemId);
        return (key in invalidItems) && (invalidItems[key] > 2);
    }

    function itemAccepted(itemId) {
        var key = getItemKey(itemId);
        if (key in acceptedItems) {
            acceptedItems[key]++;
        } else {
            acceptedItems[key] = 1;
        }
        displayAcceptedItems();
        nextItem();
    }

    function nextItem() {
        if (giftTokens.length === 0) {
            if (acceptTab) {
                chrome.tabs.remove(acceptTab.id);
                acceptTab = null;
            }
            $("#claimGifts,#acceptGifts").attr("disabled", false);
        } else {
            sendItem();
        }
    }

    function displayAcceptedItems() {
        var $ul = $("<ul></ul>");
        for (var key in acceptedItems) {
            var itemId = key.substring(7);
            var imageUrl = "http://static-cdn.playfish.com/game/cooking/gifts/v4/" + itemId + ".png";
            var $li = $("<li></li>").appendTo($ul);
            $("<img/>").attr("src", imageUrl).appendTo($li);
            $("<span></span>").text("x " + acceptedItems[key]).appendTo($li);
        }
        $("#shelf").empty().append($ul);
    }

    // on receiving session data from accept.js
    chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
        var itemId = request["itemId"];
        switch (request["status"]) {
            case "accepted":
                itemAccepted(itemId);
                break;
            case "expired":
                nextItem();
                break;
            case "invalid":
                nextItem();
                break;
        }
    });

})(jQuery);
